package com.rzl.expense.quartz.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;

/**
 * csv助手
 *
 * @author Administrator
 * @date 2023/08/06
 */
@Slf4j
public class CsvHelper {
    private CsvHelper() {
    }

    public static CsvHelper getHelper() {
        return new CsvHelper();
    }

    /**
     * 读取csv文件，并转换成List<Map<String, String>>
     *
     * @param data       数据文件
     * @param limit      限制行数 -1 表示不限制
     * @param headerLine headerLine
     * @return 转换map 对象
     */
    public List<Map<String, Object>> read(byte[] data, Integer limit, Integer
            headerLine) {
// 读取文件参数设置，根据实际情况设置
        CSVFormat format =
                CSVFormat.Builder.create()
                        .setDelimiter(',')
                        .setRecordSeparator("\r\n")
                        .setIgnoreEmptyLines(true)
                        .setAllowDuplicateHeaderNames(true)
                        .build();
//https://blog.csdn.net/sinat_35626559/article/details/106332058 --乱码报错问题
        try (CSVParser parser = format.parse(new BufferedReader(new
                InputStreamReader(new ByteArrayInputStream(data), "utf-8")))) {
            return extractDataWithHeader(parser, limit, headerLine);
        } catch (Exception e) {
            log.error("csv读取错误！", e);
        }
        return null;
    }

    /**
     * 这里处理了一种常见情况，正常字段中有换行符，就是一条数据被分成两条，这里的处理是反手拼接
     * 起来
     */
    private List<Map<String, Object>> extractDataWithHeader(CSVParser parser,
                                                            int limit, int headerLine) {
        final List<Map<String, Object>> result = new LinkedList<>();
        List<String> headers = new ArrayList<>();
        for (CSVRecord row : parser) {
            final long rowNum = row.getRecordNumber();
            if (rowNum == headerLine) {
                headers = row.stream().collect(Collectors.toList());
                continue;
            }
            result.add(setRowRecord(headers, row));
// 限制行数
            if (limit >= 0 && rowNum > limit) {
                return result;
            }
        }
        return result;
    }

    /**
     * 设置行记录
     *
     * @param headers 头
     * @param row     行
     * @return {@link Map}<{@link String}, {@link Object}>
     */
    private Map<String, Object> setRowRecord(List<String> headers, CSVRecord
            row) {
        Map<String, Object> rowRecord = new HashMap<>(headers.size());
        for (int i = 0; i < headers.size(); i++) {
            if (i < row.size()) {
                rowRecord.put(headers.get(i), row.get(i));
            }
        }
        return rowRecord;
    }
}